{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.chdir(os.path.split(os.getcwd())[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import gym\n",
    "from agent import *\n",
    "from optionpricing import *\n",
    "import yaml\n",
    "import torch\n",
    "from collections import defaultdict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.style as style"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "style.use('seaborn-poster')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "experiment_folder = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join('experiments', experiment_folder, 'config.yaml'), 'r') as f:\n",
    "    args_dict = yaml.load(f, Loader = yaml.SafeLoader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Args:\n",
    "    def __init__(self, **kwargs):\n",
    "        self.__dict__.update(kwargs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "args = Args(**args_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = {\n",
    "        'S': 100,\n",
    "        'T': 10, # 10 days\n",
    "        'L': 1,\n",
    "        'm': 100, # L options for m stocks\n",
    "        'n': 0,\n",
    "        'K': [95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105],\n",
    "        'D': 5,\n",
    "        'mu': 0,\n",
    "        'sigma': 0.01,\n",
    "        'r': 0,\n",
    "        'ss': 5,\n",
    "        'kappa': 0.1,\n",
    "        'multiplier': args.trc_multiplier,\n",
    "        'ticksize': args.trc_ticksize\n",
    "        }\n",
    "\n",
    "env = OptionPricingEnv(config)\n",
    "env.configure()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_estimator(env, device, nhidden, nunits, experiment_folder, kind = 'best'):\n",
    "    state_shape = env.observation_space.shape\n",
    "    state_space_dim = state_shape[0] if len(state_shape) == 1 else state_shape\n",
    "    \n",
    "    estimator = Estimator(nhidden, nunits, state_space_dim, env.action_space.n)\n",
    "    if kind == 'best':\n",
    "        checkpoint = torch.load(os.path.join('experiments', experiment_folder, 'best.pt'), map_location = torch.device('cpu'))\n",
    "    elif kind == 'checkpoint':\n",
    "        checkpoint = torch.load(os.path.join('experiments', experiment_folder, 'checkpoint.pt'), map_location = torch.device('cpu'))\n",
    "    else:\n",
    "        raise ValueError('Invalid choice for kind')\n",
    "        \n",
    "    estimator.load_state_dict(checkpoint['estimator'])\n",
    "    estimator.eval()\n",
    "    \n",
    "    return estimator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def delta_neutral_policy(env):\n",
    "    return env.inv_action_map[-1 * int(env.delta * (env.L * env.m)) - env.n]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simulate_episodes(config, n = 10000, kind = 'agent'):\n",
    "    env = OptionPricingEnv(config)\n",
    "    env.configure()\n",
    "    estimator = load_estimator(env, device, args.nhidden, args.nunits, experiment_folder, 'best')\n",
    "    \n",
    "    full_history = {}\n",
    "    for i in range(1, n + 1): \n",
    "        print(f'\\r{i}/{n} | {100 * i / n:.2f} %', end = '', flush = True)\n",
    "        state = torch.from_numpy(env.reset()).to(device)\n",
    "        history = defaultdict(list)\n",
    "        done = False\n",
    "\n",
    "        while not done:\n",
    "            history['delta'].append(env.delta)\n",
    "            if kind == 'agent':\n",
    "                with torch.no_grad():\n",
    "                    action = np.argmax(estimator(state).numpy())\n",
    "            else:\n",
    "                action = delta_neutral_policy(env)\n",
    "                \n",
    "            state, reward, done, info = env.step(action)\n",
    "\n",
    "            history['reward'].append(reward)\n",
    "            history['n'].append(env.n)\n",
    "            history['stock_value'].append(env.stock_value)\n",
    "            history['option_value'].append(env.option_value)\n",
    "            history['cash'].append(env.cash)\n",
    "            history['cost'].append(info['cost'])\n",
    "            history['pnl'].append(info['pnl'])\n",
    "            state = torch.from_numpy(state).to(device)\n",
    "        full_history[i] = history\n",
    "\n",
    "    return full_history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.stats import gaussian_kde"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### K = 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config['K'] = 100\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "agent_history = simulate_episodes(config, n = 1000)\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "delta_history = simulate_episodes(config, n = 1000, kind = 'delta')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent_pnl_volatility = [np.std(agent_history[i]['pnl']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_pnl_volatility = [np.std(delta_history[i]['pnl']) for i in range(1, len(delta_history) + 1)]\n",
    "agent_costs = [sum(agent_history[i]['cost']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_costs = [sum(delta_history[i]['cost']) for i in range(1, len(delta_history) + 1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize = (12, 18), nrows = 2, ncols = 1)\n",
    "x_pnl_volatility = np.linspace(0, 25, 1000)\n",
    "x_costs = np.linspace(0, 300, 1000)\n",
    "delta_pnl_volatility_kernel = gaussian_kde(delta_pnl_volatility)\n",
    "agent_pnl_volatility_kernel = gaussian_kde(agent_pnl_volatility)\n",
    "delta_costs_kernel = gaussian_kde(delta_costs)\n",
    "agent_costs_kernel = gaussian_kde(agent_costs)\n",
    "y_delta_pnl_volatility = delta_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_agent_pnl_volatility = agent_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_delta_costs = delta_costs_kernel(x_costs)\n",
    "y_agent_costs = agent_costs_kernel(x_costs)\n",
    "ax[0].plot(x_pnl_volatility, y_delta_pnl_volatility, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_pnl_volatility):.2f}, Std: {np.std(delta_pnl_volatility):.2f}', color = 'blue')\n",
    "ax[0].plot(x_pnl_volatility, y_agent_pnl_volatility, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_pnl_volatility):.2f}, Std: {np.std(agent_pnl_volatility):.2f}', color = 'red')\n",
    "#ax[0].set_title('Volatility')\n",
    "ax[0].set_xlabel('Volatility')\n",
    "ax[0].set_ylabel('Density')\n",
    "ax[0].legend()\n",
    "ax[1].plot(x_costs, y_delta_costs, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_costs):.2f}, Std: {np.std(delta_costs):.2f}', color = 'blue')\n",
    "ax[1].plot(x_costs, y_agent_costs, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_costs):.2f}, Std: {np.std(agent_costs):.2f}', color = 'red')\n",
    "#ax[1].set_title('Costs')\n",
    "ax[1].set_xlabel('Cost')\n",
    "ax[1].set_ylabel('Density')\n",
    "ax[1].legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### K = 95"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config['K'] = 95\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "agent_history = simulate_episodes(config, n = 1000)\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "delta_history = simulate_episodes(config, n = 1000, kind = 'delta')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent_pnl_volatility = [np.std(agent_history[i]['pnl']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_pnl_volatility = [np.std(delta_history[i]['pnl']) for i in range(1, len(delta_history) + 1)]\n",
    "agent_costs = [sum(agent_history[i]['cost']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_costs = [sum(delta_history[i]['cost']) for i in range(1, len(delta_history) + 1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize = (12, 18), nrows = 2, ncols = 1)\n",
    "x_pnl_volatility = np.linspace(0, 25, 1000)\n",
    "x_costs = np.linspace(0, 300, 1000)\n",
    "delta_pnl_volatility_kernel = gaussian_kde(delta_pnl_volatility)\n",
    "agent_pnl_volatility_kernel = gaussian_kde(agent_pnl_volatility)\n",
    "delta_costs_kernel = gaussian_kde(delta_costs)\n",
    "agent_costs_kernel = gaussian_kde(agent_costs)\n",
    "y_delta_pnl_volatility = delta_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_agent_pnl_volatility = agent_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_delta_costs = delta_costs_kernel(x_costs)\n",
    "y_agent_costs = agent_costs_kernel(x_costs)\n",
    "ax[0].plot(x_pnl_volatility, y_delta_pnl_volatility, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_pnl_volatility):.2f}, Std: {np.std(delta_pnl_volatility):.2f}', color = 'blue')\n",
    "ax[0].plot(x_pnl_volatility, y_agent_pnl_volatility, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_pnl_volatility):.2f}, Std: {np.std(agent_pnl_volatility):.2f}', color = 'red')\n",
    "#ax[0].set_title('Volatility')\n",
    "ax[0].set_xlabel('Volatility')\n",
    "ax[0].set_ylabel('Density')\n",
    "ax[0].legend()\n",
    "ax[1].plot(x_costs, y_delta_costs, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_costs):.2f}, Std: {np.std(delta_costs):.2f}', color = 'blue')\n",
    "ax[1].plot(x_costs, y_agent_costs, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_costs):.2f}, Std: {np.std(agent_costs):.2f}', color = 'red')\n",
    "#ax[1].set_title('Costs')\n",
    "ax[1].set_xlabel('Cost')\n",
    "ax[1].set_ylabel('Density')\n",
    "ax[1].legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### K = 105"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config['K'] = 105\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "agent_history = simulate_episodes(config, n = 1000)\n",
    "random.seed(1)\n",
    "np.random.seed(1)\n",
    "torch.manual_seed(1)\n",
    "delta_history = simulate_episodes(config, n = 1000, kind = 'delta')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent_pnl_volatility = [np.std(agent_history[i]['pnl']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_pnl_volatility = [np.std(delta_history[i]['pnl']) for i in range(1, len(delta_history) + 1)]\n",
    "agent_costs = [sum(agent_history[i]['cost']) for i in range(1, len(agent_history) + 1)]\n",
    "delta_costs = [sum(delta_history[i]['cost']) for i in range(1, len(delta_history) + 1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize = (12, 18), nrows = 2, ncols = 1)\n",
    "x_pnl_volatility = np.linspace(0, 25, 1000)\n",
    "x_costs = np.linspace(0, 300, 1000)\n",
    "delta_pnl_volatility_kernel = gaussian_kde(delta_pnl_volatility)\n",
    "agent_pnl_volatility_kernel = gaussian_kde(agent_pnl_volatility)\n",
    "delta_costs_kernel = gaussian_kde(delta_costs)\n",
    "agent_costs_kernel = gaussian_kde(agent_costs)\n",
    "y_delta_pnl_volatility = delta_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_agent_pnl_volatility = agent_pnl_volatility_kernel(x_pnl_volatility)\n",
    "y_delta_costs = delta_costs_kernel(x_costs)\n",
    "y_agent_costs = agent_costs_kernel(x_costs)\n",
    "ax[0].plot(x_pnl_volatility, y_delta_pnl_volatility, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_pnl_volatility):.2f}, Std: {np.std(delta_pnl_volatility):.2f}', color = 'blue')\n",
    "ax[0].plot(x_pnl_volatility, y_agent_pnl_volatility, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_pnl_volatility):.2f}, Std: {np.std(agent_pnl_volatility):.2f}', color = 'red')\n",
    "#ax[0].set_title('Volatility')\n",
    "ax[0].set_xlabel('Volatility')\n",
    "ax[0].set_ylabel('Density')\n",
    "ax[0].legend()\n",
    "ax[1].plot(x_costs, y_delta_costs, lw = 1.5, label = f'Delta | Mean: {np.mean(delta_costs):.2f}, Std: {np.std(delta_costs):.2f}', color = 'blue')\n",
    "ax[1].plot(x_costs, y_agent_costs, lw = 1.5, label = f'Agent | Mean: {np.mean(agent_costs):.2f}, Std: {np.std(agent_costs):.2f}', color = 'red')\n",
    "#ax[1].set_title('Costs')\n",
    "ax[1].set_xlabel('Cost')\n",
    "ax[1].set_ylabel('Density')\n",
    "ax[1].legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
